template<class T>
class auto_ptr
{
public:
	auto_ptr(T* ptr)
		:_ptr(ptr)
	{}

	auto_ptr(auto_ptr<T>& ap)
		:_ptr(ap._ptr)
	{
		ap._ptr = nullptr;
	}

	~auto_ptr()
	{
		cout << "delete: " << _ptr << endl;
		delete _ptr;
	}

	T& operator*()
	{
		return *_ptr;
	}

	T* operator->()
	{
		return _ptr;
	}

private:
	T* _ptr;
};

template<class T>
class unique_ptr
{
public:
	unique_ptr(T* ptr)
		:_ptr(ptr)
	{}

	unique_ptr(unique_ptr<T>& ap) = delete;
	unique_ptr<T>& operator=(unique_ptr<T>& ap) = delete;

	~unique_ptr()
	{
		cout << "delete: " << _ptr << endl;
		delete _ptr;
	}

	T& operator*()
	{
		return *_ptr;
	}

	T* operator->()
	{
		return _ptr;
	}

private:
	T* _ptr;
};

template <class T> 
class shared_ptr {
public:
    shared_ptr(T* ptr = nullptr) 
    : _ptr(ptr), _pcount(new int(1))  //当直接构造时，开辟了一个空间，放对象对应的引用计数
    {}

    T& operator*() { return *_ptr; }

    T* operator->() { return _ptr; }

    ~shared_ptr() {          //如果*_pcount == 0的话，就释放所有资源
        if (--(*_pcount) == 0) {
            cout << "delete" << _ptr << endl;

            delete _ptr;
            delete _pcount;
        }
    }
	//拷贝构造
    shared_ptr(const shared_ptr<T>& sp) {   //共享所有权  (*_pcount)++;
        _pcount = sp._pcount;
        _ptr = sp._ptr;

        (*_pcount)++;
    }
	//赋值
    shared_ptr<T>& operator=(const shared_ptr<T>& sp) {   // 管理对象的改变，两者管理同一个对象
        if (_ptr == sp._ptr) {
            return *this;
        }

        if (--(*_pcount) == 0) {
            delete _pcount;
            delete _ptr;
        }

        _pcount = sp._pcount;
        _ptr = sp._ptr;
        ++(*_pcount);

        return *this;
    }
    int use_count() const { return *_pcount; } 

    T* get() const { return _ptr; }

private:
    T* _ptr;
    int* _pcount;
};
template<class T>
class weak_ptr
{
public:
	weak_ptr()
		:_ptr(nullptr)
	{}

	// 从 shared_ptr 构造 weak_ptr
	weak_ptr(const shared_ptr<T>& sp)
		:_ptr(sp.get())
	{}

	T& operator*()
	{
		return *_ptr;
	}

	T* operator->()
	{
		return _ptr;
	}
private:
	T* _ptr;
};
